package com.cctc.rds.scheduler.server.storage.leveldb;

import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode;
import org.fusesource.leveldbjni.JniDBFactory;
import org.iq80.leveldb.DB;
import org.iq80.leveldb.DBComparator;
import org.iq80.leveldb.DBFactory;
import org.iq80.leveldb.Options;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * LevelDB 内存数据库。
 */
public class LevelDB {
    private volatile static DB database;
    private static final DBComparator comparator = new DBComparator() {
        @Override
        public String name() {
            return "leveldb.BytewiseComparator";
        }

        @Override
        public byte[] findShortestSeparator(byte[] bytes, byte[] bytes1) {
            return bytes;
        }

        @Override
        public byte[] findShortSuccessor(byte[] bytes) {
            return bytes;
        }

        @Override
        public int compare(byte[] o1, byte[] o2) {
            return new String(o1).compareTo(new String(o2));
        }
    };

    public synchronized static void open(String storagePath) {
        if (database == null) {
            DBFactory factory = new JniDBFactory();
            Options options = new Options();
            options.createIfMissing(true);
            options.comparator(comparator);
            try {
                database = factory.open(ensurePathExists(storagePath), options);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else {
            throw new RuntimeException("LevelDB 数据库已打开且只能被打开一次！！！");
        }
    }

    public static DB get() {
        return database;
    }

    private static File ensurePathExists(String storagePath) {
        File file = new File(storagePath);
        if (file.exists()) {
            if (file.isDirectory()) return file;
            file.delete();
        }
        file.mkdir();
        return file;
    }

    public synchronized static void close() {
        DB ref = database;
        database = null;
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
        }
        try {
            ref.close();
        } catch (IOException e) {
        }
    }

}
